#include "../../public/_public.h"

using namespace idc;

int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        printf("\n");
        printf("Using:./checkproc logfilename\n");

        printf("Example:/root/mylib/project/tools/bin/procctl 10 /root/mylib/project/tools/bin/checkproc /tmp/log/checkproc.log\n\n");

        printf("本程序用于检查后台服务程序是否超时，如果已超时，就终止它。\n");
        printf("注意：\n");
        printf("  1）本程序由procctl启动，运行周期建议为10秒。\n");
        printf("  2）为了避免被普通用户误杀，本程序应该用root用户启动。\n");
        printf("  3）如果要停止本程序，只能用killall -9 终止。\n\n\n");
    }

        // 打开日志文件
        clogfile logfile;
        if (logfile.open(argv[1])==false)
        {
            cout<<"log.open"<<argv[1]<<"failed."<<endl;
        }

        //创建/获取共享内存
        int shmid=shmget((key_t)SHMKEYP, MAXNUM*sizeof(struct st_procinfo), 0666|IPC_CREAT);
        if(shmid==-1)
        {
            logfile.write("shmget failed.");
        }

        //将共享内存连接到进程空间
        struct st_procinfo *st_info=(struct st_procinfo *)shmat(shmid,0,0);
        if(st_info==(void *)-1)
        {
            logfile.write("shmat failed.");
        }

        //检查共享内存的进程是否超时
        for(int i=0;i<MAXNUM;i++)
        {
            if(st_info[i].pid==0) continue;
            if(st_info[i].pid>0)
            {
                //logfile.write("checkproc pid=%d,name=%s,timeout=%d,atime=%d",st_info[i].pid,st_info[i].name,st_info[i].timeout,st_info[i].atime); //主要用于测试
                //向该进程发送信号0，测试进程是否存在
                int iret=kill(st_info[i].pid,0); 
                if(iret==-1)
                {
                    //进程不存在,在共享内存中删除该进程的记录
                    memset(&st_info[i],0,sizeof(struct st_procinfo));
                    continue;
                }
                //尝试检查进程是否超时
                time_t now_time=time(0);
                if(now_time-st_info[i].atime<st_info[i].timeout) continue;
                logfile.write("进程%d超时，准备终止",st_info[i].pid);
                struct st_procinfo tmp=st_info[i]; //备份进程信息
                kill(tmp.pid,15); //首先尝试正常终止进程
                for(int j=0;j<5;j++)
                {
                    int iret=kill(tmp.pid,0);
                    if(iret==-1)
                    {
                        logfile.write("进程%d正常终止成功",tmp.pid);
                        continue; //进程不存在，说明已经正常终止;
                    }
                    sleep(1); //等待1秒 
                }

                //进程仍然存在，说明进程没有正常终止，强制终止
                kill(tmp.pid,9);
                memset(&st_info[i],0,sizeof(struct st_procinfo));
                logfile.write("进程%d强制终止成功",tmp.pid);
            }
        }
        
        //断开共享内存的连接
        shmdt(st_info);
        return 0;
}